<template>
  <div class="page_root" :key="queryUpdateFlag" data-page-name="工单按钮" data-page-identification="m_ct52qb4en2">
    <a-spin :spinning="pageLoading.loading" :tip="pageLoading.tip">
      <!-- begin vid_jvw772az8c 自定义模板_yiurj2x5rz -->
      <!--          新建sop工单-->
      <a-modal centered v-model:visible="newSopState.sopVisible" :ok-button-props="{ loading: newSopState.sopOkLoading }" :mask-closable="false" width="800px" title="+SOP子工单" @cancel="cancelSop">
        <template #footer>
          <a-space>
            <a-button type="primary" ghost @click="cancelSop">取消</a-button>
            <a-button type="primary" @click="handleDownLoadSopTemplate(currentAddSopRecord)" :loading="downTemplateFileLoading">下载附件模板</a-button>
            <a-button type="primary" @click="confirmSop" :loading="sopSonLoading">保存</a-button>
          </a-space>
        </template>
        <div class="modal-table">
          <a-table
            :columns="sopColumns"
            :data-source="newSopState.sopTableData"
            rowKey="sopStepId"
            :row-selection="{
                            selectedRowKeys: newSopState.selectedRowKeys,
                            onChange: onSopSelectChange,
                            fixed: true,
                            getCheckboxProps: record => ({
                                disabled: record.disabled // Column configuration not to be checked
                            })
                        }"
            bordered
            :pagination="false"
            :row-class-name="
                            (_record, index) => (index % 2 === 1 ? 'table-striped-even' : 'table-striped-odd')
                        "
          >
            <template #bodyCell="{ record, text, column, index }">
              <template v-if="column.dataIndex === 'sequence'">
                <a-input v-model:value="record.sequence" />
              </template>
            </template>
          </a-table>
        </div>
        <div style="margin-top: 16px">
          <a-upload v-model:file-list="newSopState.sopFileList" :multiple="true" :before-upload="handlerSopUpload" @remove="handlerSopRemove" accept=".xlsx, image/*,.docx,, .xls,.mp4">
            <a-button type="primary">
              <upload-outlined />
              上传附件
            </a-button>
          </a-upload>
        </div>
      </a-modal>
      <!--          新建sop工单-->
      <!--          解决中变更-->
      <a-modal
        centered
        v-model:visible="newState.resolvingVisible"
        title="开始解决"
        width="800px"
        destroy-on-close
        :ok-button-props="{
                    loading: newState.changeStatusLoading
                }"
        @cancel="cancelResolving"
      >
        <template #footer>
          <a-space>
            <a-button type="default" @click="cancelResolving">取消</a-button>
            <a-button type="primary" @click="handleDownLoadSopTemplate(currentResolvingData)" :loading="downTemplateFileLoading" v-if="currentResolvingData.tag === 1">下载附件模板</a-button>
            <a-button type="primary" @click="confirmResolving" :loading="newState.changeStatusLoading">确定</a-button>
          </a-space>
        </template>
        <template v-if="currentResolvingData.tag === 1 && !currentResolvingData.parentId">
          <div class="sop-start-tip">
            <ExclamationCircleOutlined style="color: #fab221" />
            请选择执行SOP工单，不选择则不建立SOP子工单，直接开始工单任务。
          </div>
          <div class="modal-table">
            <a-table
              :columns="sopColumns"
              :data-source="newSopState.sopTableData"
              rowKey="sopStepId"
              :row-selection="{
                                selectedRowKeys: newSopState.selectedRowKeys,
                                onChange: onSopSelectChange,
                                fixed: true,
                                getCheckboxProps: record => ({
                                    disabled: record.disabled // Column configuration not to be checked
                                })
                            }"
              :row-class-name="
                                (_record, index) => (index % 2 === 1 ? 'table-striped-even' : 'table-striped-odd')
                            "
              bordered
              :pagination="false"
            >
              <template #bodyCell="{ record, text, column, index }">
                <template v-if="column.dataIndex === 'sequence'">
                  <a-input v-model:value="record.sequence" />
                </template>
              </template>
            </a-table>
          </div>
        </template>
        <div class="change-status-tip" v-else> 确定开始处理工单吗 </div>
        <!--              如果是sop父工单展示这个-->
      </a-modal>
      <!--          解决中变更-->
      <!--          已解决变更-->
      <a-modal
        centered
        v-model:visible="newState.resolvedVisible"
        title="已解决"
        width="1000px"
        :body-style="{
                    paddingBottom: 0,
                    maxHeight: '800px',
                    overflowY: 'auto'
                }"
        destroy-on-close
        :ok-button-props="{
                    loading: newState.changeStatusLoading
                }"
      >
        <template #footer>
          <a-space>
            <a-button type="default" @click="cancelResolved">取消</a-button>
            <a-button v-if="resolvedData.tag === 1" type="primary" @click="handleDownLoadSopTemplate(resolvedData)" :loading="downTemplateFileLoading">下载附件模板</a-button>
            <a-button type="primary" @click="saveRoot" :loading="newState.changeStatusLoading">确定</a-button>
          </a-space>
        </template>
        <div class="change-status">
          <template v-if="resolvedData.tag === 1">
            <div class="change-status-resolved">
              <div class="resolved-div">
                <ExclamationCircleOutlined style="color: #fab221; margin-top: 3px" />
                <div>
                  请确认是否完成该工单？如该步骤包含附件请上传；<br />
                  您可以在勾选建立【剩余SOP子工单】，推进父工单解决；<br />
                  并行SOP子工单解决人不支持重复建立【剩余SOP子工单】，已建立的将为您过滤；<br />
                  并行SOP子工单解决人全部未勾选建立【剩余SOP子工单】，父工单直接进入已解决状态；<br />
                </div>
              </div>
              <div class="upload-file">
                <a-upload
                  v-model:file-list="newState.resolvedForm.attachmentList"
                  :multiple="true"
                  :before-upload="handlerResolvedUpload"
                  @remove="handlerResolvedRemove"
                  accept=".xlsx, image/*,.docx,, .xls,.mp4"
                >
                  <a-button type="primary" ghost style="background: rgba(56, 117, 255, 0.1)">
                    <upload-outlined />
                    上传附件
                  </a-button>
                </a-upload>
              </div>
            </div>
            <div class="modal-table" style="margin-bottom: 16px">
              <a-table
                :columns="sopColumns"
                :data-source="newSopState.solvedSOPList"
                bordered
                :pagination="false"
                :row-class-name="
                                    (_record, index) => (index % 2 === 1 ? 'table-striped-even' : 'table-striped-odd')
                                "
              />
            </div>
          </template>
          <template v-if="!resolvedData.parentId">
            <a-form :model="rootState" ref="rootRef">
              <a-row :gutter="24">
                <a-col :span="6">
                  <a-form-item label="责任方" :labelCol="{ span: 8 }" :wrapperCol="{ span: 16 }" :rules="[{ required: true, message: '请选择责任方', trigger: 'blur' }]" name="responsibleParty">
                    <a-select
                      allow-clear
                      show-search
                      style="width: 100%"
                      v-model:value="rootState.responsibleParty"
                      :options="rootState.responsiblePartyList"
                      placeholder="请选择"
                      :field-names="{ label: 'itemName', value: 'itemName' }"
                      :filterOption="
                                                (input, option) => {
                                                    return (
                                                        option.itemName.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                    )
                                                }
                                            "
                      @focus="getResponsiblePartyList"
                      @change="responsiblePartyChange"
                    />
                  </a-form-item>
                </a-col>
                <a-col :span="6">
                  <a-form-item label="业务类型" :labelCol="{ span: 9 }" :wrapperCol="{ span: 15 }" :rules="[{ required: true, message: '请选择业务类型', trigger: 'blur' }]" name="businessType">
                    <a-select
                      allow-clear
                      show-search
                      style="width: 100%"
                      v-model:value="rootState.businessType"
                      :options="rootState.businessTypeList"
                      placeholder="请选择"
                      :field-names="{ label: 'itemName', value: 'itemName' }"
                      :filterOption="
                                                (input, option) => {
                                                    return (
                                                        option.itemName.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                    )
                                                }
                                            "
                      @focus="getBusinessTypeList"
                      @change="businessTypeChange"
                    />
                  </a-form-item>
                </a-col>
                <a-col :span="12">
                  <a-form-item label="根因分析" :labelCol="{ span: 4 }" :wrapperCol="{ span: 20 }" :rules="[{ required: true, message: '请选择根因分析', trigger: 'blur' }]" name="rootCauseClassify">
                    <a-select
                      allow-clear
                      show-search
                      style="width: 100%"
                      v-model:value="rootState.rootCauseClassify"
                      :options="rootState.rootCauseClassifyList"
                      placeholder="请选择"
                      :field-names="{ label: 'itemName', value: 'itemName' }"
                      :filterOption="
                                                (input, option) => {
                                                    return (
                                                        option.itemName.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                    )
                                                }
                                            "
                      @focus="getRootCauseClassifyList"
                      @change="rootCauseClassifyChange"
                    />
                  </a-form-item>
                </a-col>
              </a-row>
            </a-form>
            <a-form-item label="根因详情">
              <QuillEditor ref="rootQuillEditor" :options="editorOption" class="quill-editor" />
            </a-form-item>
          </template>

          <a-form :model="newState.resolvedForm" ref="resolvedFormRef" style="margin-top: 16px">
            {{ newState.solutionDetail }}
            <a-row>
              <a-col :span="24">
                <a-form-item label="解决方案详述" :rules="newRules.solutionDetail" name="solutionDetail">
                  <QuillEditor ref="resolvedQuillRef" :options="editorOption" class="quill-editor" v-model:content="newState.resolvedForm.solutionDetail"
                /></a-form-item>
              </a-col>
            </a-row>
          </a-form>
          <template v-if="resolvedData.tag === 1 && resolvedData.parentId">
            <div class="modal-sop-title">剩余SOP工单</div>
            <div class="modal-table">
              <a-table
                :columns="sopColumns"
                :data-source="newSopState.sopTableData"
                rowKey="sopStepId"
                :row-selection="{
                                    selectedRowKeys: newSopState.selectedRowKeys,
                                    onChange: onSopSelectChange,
                                    fixed: true,
                                    getCheckboxProps: record => ({
                                        disabled: record.disabled // Column configuration not to be checked
                                    })
                                }"
                :row-class-name="
                                    (_record, index) => (index % 2 === 1 ? 'table-striped-even' : 'table-striped-odd')
                                "
                bordered
                :pagination="false"
              />
            </div>
          </template>
        </div>
      </a-modal>
      <!--          已解决变更-->
      <!--          无需解决-->
      <a-modal
        :visible="sonState.noNeedVisible"
        centered
        destroy-on-close
        @cancel="cancelNoNeed"
        @ok="submitNoNeed"
        width="800px"
        title="无需解决"
        :mask-closable="false"
        :ok-button-props="{ loading: sonState.noNeedLoading }"
      >
        <!--              如果是sop展示-->
        <div class="no-need-tip" v-if="noNeedData.tag === 1 && noNeedData.parentId">
          <ExclamationCircleOutlined style="color: #fab221" />
          请确认是否无需解决该工单？<br />
          您可以在勾选建立【剩余SOP子工单】，推进父工单解决；<br />
          并行SOP子工单解决人不支持重复建立【剩余SOP子工单】，已建立的将为您过滤；<br />
          并行SOP子工单解决人全部未勾选建立【剩余SOP子工单】，父工单直接进入已解决状态；<br />
        </div>
        <div class="no-need-tip" v-else>
          <ExclamationCircleOutlined style="color: #fab221" />
          请确认是否无需解决该工单？请填写备注注明原因。
        </div>
        <a-form ref="noNeedRef" :model="sonState">
          <a-form-item label="备注" :rules="[{ required: true, message: '请输入备注', trigger: 'blur' }]" name="noNeedRemark">
            <a-textarea v-model:value="sonState.noNeedRemark" :rows="4" />
          </a-form-item>
        </a-form>
        <template v-if="noNeedData.tag === 1 && noNeedData.parentId">
          <div class="modal-sop-title">剩余SOP</div>
          <div class="modal-table">
            <a-table
              :columns="sopColumns"
              :data-source="newSopState.sopTableData"
              rowKey="sopStepId"
              :row-selection="{
                                selectedRowKeys: newSopState.selectedRowKeys,
                                onChange: onSopSelectChange,
                                fixed: true,
                                getCheckboxProps: record => ({
                                    disabled: record.disabled // Column configuration not to be checked
                                })
                            }"
              bordered
              :pagination="false"
              :row-class-name="
                                (_record, index) => (index % 2 === 1 ? 'table-striped-even' : 'table-striped-odd')
                            "
            />
          </div>
        </template>
      </a-modal>
      <!--          无需解决-->
      <!--          关闭工单-->
      <a-modal
        :visible="newSopState.sopCloseVisible"
        centered
        @cancel="cancelClose"
        @ok="confirmSopClose"
        destroy-on-close
        width="800px"
        title="关闭"
        :mask-closable="false"
        :ok-button-props="{ loading: newSopState.closeLoading }"
      >
        <!--              如果是sop展示-->
        <div class="no-need-tip" v-if="currentCloseData.tag === 1 && currentCloseData.parentId">
          <ExclamationCircleOutlined style="color: #fab221" />
          请确认是否关闭该工单？ 您可以在勾选建立【剩余SOP子工单】，推进父工单解决； 并行SOP子工单解决人不支持重复建立【剩余SOP子工单】，已建立的将为您过滤；
          并行SOP子工单解决人全部未勾选建立【剩余SOP子工单】，父工单直接进入已解决状态；
        </div>
        <div class="no-need-tip" v-else>
          <ExclamationCircleOutlined style="color: #fab221" />
          请确认是否关闭该工单？请填写备注注明原因
        </div>
        <a-form ref="closeRef" :model="newSopState">
          <a-form-item label="备注" :rules="[{ required: true, message: '请输入备注', trigger: 'blur' }]" name="closeRemark">
            <a-textarea v-model:value="newSopState.closeRemark" :rows="4" />
          </a-form-item>
        </a-form>
        <div class="modal-sop-title" v-if="currentCloseData.tag === 1 && currentCloseData.parentId">剩余SOP</div>
        <div class="modal-table" v-if="currentCloseData.tag === 1 && currentCloseData.parentId">
          <a-table
            :columns="sopColumns"
            :data-source="newSopState.sopTableData"
            rowKey="sopStepId"
            :row-selection="{
                            selectedRowKeys: newSopState.selectedRowKeys,
                            onChange: onSopSelectChange,
                            fixed: true,
                            getCheckboxProps: record => ({
                                disabled: record.disabled // Column configuration not to be checked
                            })
                        }"
            :row-class-name="
                            (_record, index) => (index % 2 === 1 ? 'table-striped-even' : 'table-striped-odd')
                        "
            bordered
            :pagination="false"
          />
        </div>
      </a-modal>
      <!--          关闭工单-->
      <!--          新建/编辑工单-->
      <a-modal
        centered
        v-model:visible="state.addOrEditVisible"
        :title="state.modalTitle"
        @ok="submit"
        @cancel="fatherCancel"
        width="1000px"
        destroy-on-close
        :ok-button-props="{ loading: state.fatherLoading }"
      >
        <div class="form-content">
          <a-form :model="state.modalForm" ref="formRef">
            <a-row>
              <a-col :span="24">
                <a-form-item label="工单标题" :rules="[{ required: true, message: '请输入工单标题', trigger: 'blur' }]" name="content">
                  <a-textarea maxlength="100" show-count placeholder="请输入" v-model:value="state.modalForm.content" />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="工单类型" :rules="[{ required: true, message: '请选择工单类型', trigger: 'blur' }]" name="type">
                  <a-select
                    :options="state.workTypeList"
                    v-model:value="state.modalForm.type"
                    placeholder="请选择"
                    :field-names="{ label: 'label', value: 'value' }"
                    :filterOption="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                    @change="hanldeTypeChange"
                  />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="监控场景">
                  <a-select
                    show-search
                    :options="state.monitorSceneList"
                    :field-names="{ label: 'label', value: 'value' }"
                    :filterOption="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                    allow-clear
                    v-model:value="state.modalForm.monitorScene"
                    placeholder="请选择"
                    @focus="getMonitorSceneList(false)"
                  />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="优先级" :rules="[{ required: true, message: '请选择优先级', trigger: 'blur' }]" name="priority">
                  <a-select
                    :disabled="state.modalForm.type === '产品需求'"
                    v-model:value="state.modalForm.priority"
                    :options="[
                                            {
                                                label: 'p0',
                                                value: 'p0'
                                            },
                                            {
                                                label: 'p1',
                                                value: 'p1'
                                            },
                                            {
                                                label: 'p2',
                                                value: 'p2'
                                            },
                                            {
                                                label: 'p3',
                                                value: 'p3'
                                            }
                                        ]"
                    placeholder="请选择"
                    @change="getSolveTimeByType"
                  />
                </a-form-item>
              </a-col>
              <a-col :span="12" v-if="state.modalForm.type !== '产品需求'">
                <a-form-item
                  label="计划解决时长(小时)"
                  :rules="[
                                        {
                                            pattern: new RegExp(/^(0(\.5)?|[1-9](\d*)?(\.5)?(\.0)?)$/),
                                            message: '请输入大于0的数字(支持0.5的倍数)',
                                            trigger: 'blur'
                                        }
                                    ]"
                  name="workHours"
                >
                  <a-input-number placeholder="请输入" v-model:value="state.modalForm.workHours" @change="getSolveTime" />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="计划解决时间" :rules="[{ required: true, message: '请选择计划解决时间', trigger: 'blur' }]" name="endTime">
                  <a-date-picker show-time placeholder="请选择" v-model:value="state.modalForm.endTime" value-format="YYYY-MM-DD HH:mm:ss" />
                </a-form-item>
              </a-col>
            </a-row>
            <a-row>
              <a-col :span="12">
                <a-form-item label="问题来源" :rules="[{ required: true, message: '请选择问题来源', trigger: 'blur' }]" name="questionSource">
                  <a-select v-model:value="state.modalForm.questionSource" :options="state.wtlyList" placeholder="请选择" />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="所属区域" :rules="[{ required: true, message: '请选择所属区域', trigger: 'blur' }]" name="areaCode">
                  <a-select
                    allow-clear
                    show-search
                    :options="state.areaList"
                    placeholder="请选择"
                    v-model:value="state.modalForm.areaCode"
                    @focus="getAreaList"
                    :field-names="{ label: 'label', value: 'value' }"
                    :filter-option="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                    @change="areaChange"
                  />
                </a-form-item>
              </a-col>
            </a-row>
            <a-row>
              <a-col :span="12">
                <a-form-item
                  label="所属客户"
                  :rules="[
                                        {
                                            required: currentData.questionSource === '问题转化' ? false : true,
                                            message: '请输入所属客户',
                                            trigger: 'blur'
                                        }
                                    ]"
                  name="customer"
                >
                  <a-select
                    allow-clear
                    show-search
                    :options="state.customList"
                    placeholder="请选择"
                    v-model:value="state.modalForm.customer"
                    @focus="getCustomerList"
                    :field-names="{ label: 'name', value: 'name' }"
                    :filter-option="
                                            (input, option) => {
                                                return option.name.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                    @change="customerChange"
                  />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="所属项目" :rules="[{ required: true, message: '请选择所属项目', trigger: 'blur' }]" name="projectId">
                  <a-select
                    allow-clear
                    show-search
                    :options="state.projectList"
                    placeholder="请选择"
                    v-model:value="state.modalForm.projectId"
                    :field-names="{ label: 'projectName', value: 'projectId' }"
                    :filter-option="
                                            (input, option) => {
                                                return (
                                                    option.projectName.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                )
                                            }
                                        "
                    @focus="getProjectList"
                    @change="projectChange"
                  />
                </a-form-item>
              </a-col>
            </a-row>
            <a-row>
              <a-col :span="12">
                <a-form-item label="项目阶段">
                  <a-select
                    allow-clear
                    show-search
                    :options="state.milepostList"
                    placeholder="请选择"
                    v-model:value="state.modalForm.milepostId"
                    :field-names="{ label: 'milepostName', value: 'milepostId' }"
                    :filter-option="
                                            (input, option) => {
                                                return (
                                                    option.milepostName.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                )
                                            }
                                        "
                    @focus="getMilepostList"
                    @change="milepostChange"
                  />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="任务名称">
                  <a-select
                    allow-clear
                    show-search
                    :options="state.taskList"
                    placeholder="请选择"
                    v-model:value="state.modalForm.taskId"
                    :field-names="{ label: 'taskName', value: 'taskId' }"
                    :filter-option="
                                            (input, option) => {
                                                return option.taskName.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                    @focus="getTaskList"
                  />
                </a-form-item>
              </a-col>
            </a-row>
            <a-row>
              <a-col :span="12">
                <a-form-item
                  label="环境"
                  :rules="[
                                        {
                                            required: currentData.questionSource === '问题转化' ? false : true,
                                            message: '请选择环境',
                                            trigger: 'blur'
                                        }
                                    ]"
                  name="environment"
                >
                  <a-select
                    show-search
                    allow-clear
                    :options="state.environmentList"
                    placeholder="请选择"
                    v-model:value="state.modalForm.environment"
                    :field-names="{ label: 'name', value: 'name' }"
                    :filter-option="
                                            (input, option) => {
                                                return option.name.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                    @focus="getEnvironmentList"
                    @change="environmentChange"
                  />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item
                  label="所属产品"
                  :rules="[
                                        {
                                            required: currentData.questionSource === '问题转化' ? false : true,
                                            message: '请选择所属产品',
                                            trigger: 'blur'
                                        }
                                    ]"
                  name="production"
                >
                  <a-select
                    show-search
                    allow-clear
                    :options="state.productList"
                    placeholder="请选择"
                    v-model:value="state.modalForm.production"
                    @change="productChange"
                    @focus="getProductList"
                    :field-names="{ label: 'name', value: 'name' }"
                    :filter-option="
                                            (input, option) => {
                                                return option.name.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                  />
                </a-form-item>
              </a-col>
            </a-row>
            <a-row>
              <a-col :span="12">
                <a-form-item label="版本">
                  <a-input v-model:value="state.modalForm.version" disabled />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="告警级别">
                  <a-select
                    show-search
                    allow-clear
                    :options="state.warnList"
                    placeholder="请选择"
                    v-model:value="state.modalForm.warningLevel"
                    :field-names="{ label: 'label', value: 'label' }"
                    :filter-option="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                  />
                </a-form-item>
              </a-col>
            </a-row>
            <div
              class="description-tip"
              v-if="
                                (currentData.status !== '未开始' || currentData.status !== '待分发') &&
                                currentData.status
                            "
              ><ExclamationCircleFilled class="tip-img" /> 解决中的工单不支持编辑问题描述</div
            >
            <a-row
              :style="{
                                pointerEvents:
                                    currentData.status === '未开始' ||
                                    !currentData.status ||
                                    currentData.status === '待分发'
                                        ? 'auto'
                                        : 'none'
                            }"
            >
              <a-col :span="24">
                <a-form-item label="问题描述" :rules="[{ required: true, message: '请输入问题描述', trigger: 'blur' }]" name="qillData">
                  <QuillEditor v-model:content="state.modalForm.qillData" ref="quillEditor" :options="editorOption" class="quill-editor" />
                </a-form-item>
              </a-col>
            </a-row>
            <!--                        <a-row>-->
            <!--                            <a-col :span="24">-->
            <!--                                <a-form-item-->
            <!--                                    label="解决人"-->
            <!--                                    :rules="[{ required: true, message: '请选择解决人', trigger: 'blur' }]"-->
            <!--                                    name="solverList"-->
            <!--                                >-->
            <!--                                    <a-select-->
            <!--                                        class="remove-icon"-->
            <!--                                        show-search-->
            <!--                                        mode="multiple"-->
            <!--                                        :options="state.allUser"-->
            <!--                                        v-model:value="state.modalForm.solverList"-->
            <!--                                        placeholder="请选择"-->
            <!--                                        :field-names="{ label: 'name', value: 'name' }"-->
            <!--                                        :filter-option="-->
            <!--                                            (input, option) => {-->
            <!--                                                return option.name.toLowerCase().indexOf(input.toLowerCase()) >= 0-->
            <!--                                            }-->
            <!--                                        "-->
            <!--                                        @change="fatherSolverChange"-->
            <!--                                    />-->
            <!--                                </a-form-item>-->
            <!--                            </a-col>-->
            <!--                        </a-row>-->
            <!--                        &lt;!&ndash;                      <a-col v-if="taskPeopleList.length > 0">&ndash;&gt;-->
            <!--                        <a-col>-->
            <!--                            <div style="width: 700px; margin-left: 135px; margin-bottom: 16px">-->
            <!--                                <a-->
            <!--                                    href="javascript:;"-->
            <!--                                    v-for="(item, num) in taskPeopleList"-->
            <!--                                    @click="handlerAddPeople(item.value, index)"-->
            <!--                                    ><span style="margin: 0 5px">{{ item.value }}</span></a-->
            <!--                                >-->
            <!--                            </div>-->
            <!--                        </a-col>-->
            <a-col :span="24">
              <a-form-item label="上传附件">
                <a-upload
                  v-model:file-list="state.modalForm.descriptionAttachmentList"
                  :multiple="true"
                  :before-upload="handlerFatherUpload"
                  @remove="handlerFatherRemove"
                  accept=".xlsx, image/*,.docx,, .xls,.mp4"
                >
                  <a-button type="primary">
                    <upload-outlined />
                    上传
                  </a-button>
                </a-upload>
                <span>支持格式：.xlsx, image/*,.docx,, .xls,.mp4</span>
              </a-form-item>
            </a-col>
          </a-form>
        </div>
      </a-modal>
      <!--          新建/编辑工单-->
      <!--          流转变更-->
      <a-modal
        centered
        v-model:visible="newState.circulationVisible"
        title="流转"
        width="520px"
        @ok="confirmCirculation"
        destroy-on-close
        :body-style="{
                    paddingBottom: 0
                }"
        :ok-button-props="{
                    loading: newState.changeStatusLoading
                }"
        @cancel="cancelCirculation"
      >
        <div class="change-status">
          <a-form :model="newState.circulationForm" ref="circulationFormRef">
            <a-row>
              <a-col :span="24">
                <a-form-item label="解决人" :rules="[{ required: true, message: '请选择解决人', trigger: 'blur' }]" name="solverList">
                  <a-select
                    class="remove-icon"
                    show-search
                    :allow-clear="false"
                    mode="multiple"
                    :options="state.allUser"
                    v-model:value="newState.circulationForm.solverList"
                    placeholder="请选择"
                    :field-names="{ label: 'name', value: 'name' }"
                    :filter-option="
                                            (input, option) => {
                                                return option.name.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                    @change="changeStatusSolverChange"
                  />
                </a-form-item>
              </a-col>
            </a-row>
          </a-form>
        </div>
      </a-modal>
      <!--          流转变更-->
      <!--          删除-->
      <a-modal centered v-model:visible="state.deleteVisible" title="删除" @ok="handleDelete" :ok-button-props="{ loading: state.deleteLoading }">
        <!--                请确认是否删除该工单任务，如该工单建立了子工单请先对子工单进行解决后在进行删除操作。-->
        <a-form ref="deleteRef" :model="sonState">
          <a-form-item label="备注" :rules="[{ required: true, message: '请输入备注', trigger: 'blur' }]" name="deleteRemark">
            <a-textarea v-model:value="sonState.deleteRemark" :rows="4" />
          </a-form-item>
        </a-form>
      </a-modal>
      <!--          删除-->
      <!--          编辑子工单-->
      <a-modal centered v-model:visible="state.editSonVisible" :title="sonState.modalTitle" @ok="submitSon" width="1000px" :ok-button-props="{ loading: state.sonLoading }" @cancel="cancelSon">
        <div class="form-content">
          <a-form :model="state.sonForm" ref="sonRef">
            <a-row>
              <a-col :span="24">
                <a-form-item label="工单标题" :rules="[{ required: true, message: '请输入工单标题', trigger: 'blur' }]" name="content">
                  <a-input maxlength="100" show-count placeholder="请输入" v-model:value="state.sonForm.content" />
                </a-form-item>
              </a-col>
            </a-row>

            <a-row>
              <!--                            <a-col :span="24">-->
              <!--                                <a-form-item-->
              <!--                                    label="计划解决时间"-->
              <!--                                    :rules="[{ required: false, message: '请选择计划解决时间', trigger: 'blur' }]"-->
              <!--                                    name="endTime"-->
              <!--                                >-->
              <!--                                    <a-date-picker-->
              <!--                                        show-time-->
              <!--                                        placeholder="请选择"-->
              <!--                                        v-model:value="state.sonForm.endTime"-->
              <!--                                        value-format="YYYY-MM-DD HH:mm:ss"-->
              <!--                                    />-->
              <!--                                </a-form-item>-->
              <!--                            </a-col>-->
              <a-col :span="24">
                <div
                  class="description-tip"
                  v-if="
                                        (currentData.status !== '未开始' || currentData.status !== '待分发') &&
                                        currentData.status
                                    "
                  ><ExclamationCircleFilled class="tip-img" /> 解决中的工单不支持编辑问题描述</div
                >
              </a-col>
            </a-row>
            <a-row>
              <a-col
                :span="24"
                :style="{
                                    pointerEvents:
                                        currentData.status === '未开始' ||
                                        !currentData.status ||
                                        currentData.status === '待分发'
                                            ? 'auto'
                                            : 'none'
                                }"
              >
                <a-form-item label="问题描述" :rules="[{ required: true, message: '请输入问题描述', trigger: 'blur' }]" name="quillData">
                  <QuillEditor ref="sonQuillRef" v-model:content="state.sonForm.quillData" :options="editorOption" class="quill-editor" />
                </a-form-item>
              </a-col>
            </a-row>
            <a-col :span="24">
              <a-form-item label="上传附件">
                <a-upload
                  v-model:file-list="state.sonForm.descriptionAttachmentList"
                  :multiple="true"
                  :before-upload="handlerSonUpload"
                  @remove="handlerSonRemove"
                  accept=".xlsx, image/*,.docx,, .xls,.mp4"
                >
                  <a-button type="primary">
                    <upload-outlined />
                    上传
                  </a-button>
                </a-upload>
                <span>支持格式：.xlsx, image/*,.docx,, .xls,.mp4</span>
              </a-form-item>
            </a-col>
          </a-form>
        </div>
      </a-modal>
      <!--          编辑子工单-->
      <div class="body">
        <div class="father-last">
          <!--                    <a-button-->
          <!--                        v-if="!state.gdDetail.parentId"-->
          <!--                        ghost-->
          <!--                        type="primary"-->
          <!--                        @click="handleAddSon(state.gdDetail)"-->
          <!--                        -->
          <!--                        :disabled="sonDisabled(state.gdDetail)"-->
          <!--                        ><template #icon> <ContainerOutlined /> </template>子工单</a-button-->
          <!--                    >-->
          <!--                    <a-button-->
          <!--                        v-if="!state.gdDetail.parentId"-->
          <!--                        ghost-->
          <!--                        type="primary"-->
          <!--                        :disabled="sopDisabled(state.gdDetail)"-->
          <!--                        @click="handleAddSopSon(state.gdDetail)"-->
          <!--                        -->
          <!--                        class="btn-body"-->
          <!--                    >-->
          <!--                        &lt;!&ndash;                                <template #icon> <plus-outlined /> </template>SOP子工单</a-button&ndash;&gt;-->
          <!--                        &lt;!&ndash;                            >&ndash;&gt;-->
          <!--                        <template #icon> <FileAddOutlined /></template>SOP子工单</a-button-->
          <!--                    >-->

          <template v-if="['已解决', '无需解决'].includes(state.gdDetail.status)">
            <a-popconfirm title="请确认是否重新打开工单？" @confirm="handlerReOpen(state.gdDetail)">
              <a-button type="primary" ghost class="btn-item">
                <template #icon><RedoOutlined /></template>
                重新打开</a-button
              >
            </a-popconfirm>
          </template>
          <template v-else>
            <a-button type="primary" class="btn-item" @click="showResolving(state.gdDetail)" :disabled="isResolvingDisabled(state.gdDetail)">开始解决</a-button>
          </template>

          <a-button type="primary" class="btn-item" @click="showCirculation(state.gdDetail)" :disabled="isCirculationDisabled(state.gdDetail)"> 流转 </a-button>
          <a-button type="primary" class="btn-item" @click="showResolved(state.gdDetail)" :disabled="isResolvedDisabled(state.gdDetail)"> 已解决 </a-button>

          <a-button type="primary" class="btn-item" :disabled="isCloseDisabled(state.gdDetail)" @click="handlerClose(state.gdDetail)"> 关闭 </a-button>

          <a-dropdown placement="bottomRight">
            <a class="ant-dropdown-link"> <EllipsisOutlined style="color:#3875ff; font-size: 16px" /></a>
            <template #overlay>
              <a-menu>
                <a-menu-item>
                  <a-button type="primary" class="btn-item" @click="showNoNeed(state.gdDetail)" :disabled="isNoNeedSolveDisabled(state.gdDetail)"> 无需解决</a-button>
                </a-menu-item>
                <a-menu-item>
                  <a-button type="primary" v-if="state.gdDetail.parentId" class="btn-item" @click="editSon(state.gdDetail)" :disabled="isEditDisabled(state.gdDetail)"> 编辑 </a-button>
                  <a-button type="primary" v-if="!state.gdDetail.parentId" class="btn-item" @click="handleEdit(state.gdDetail)" :disabled="isEditDisabled(state.gdDetail)"> 编辑 </a-button>
                </a-menu-item>
                <a-menu-item>
                  <a-button
                    type="primary"
                    class="btn-item"
                    @click="toDelete(state.gdDetail)"
                    :disabled="
                            !(
                                (state.gdDetail.status === '未开始' || state.gdDetail.status === '待分发') &&
                                state.gdDetail.myCreated
                            )
                        "
                  >
                    删除
                  </a-button>
                </a-menu-item>
                <a-menu-item>
                  <a-popconfirm title="请确认是否提醒该工单相关人员？" @confirm="toRmind(state.gdDetail.id)" :disabled="!state.gdDetail.pmoOrNot">
                    <a-button type="primary" class="btn-item" :disabled="!state.gdDetail.pmoOrNot"> 催办 </a-button>
                  </a-popconfirm>
                </a-menu-item>
                <a-menu-item>
                  <a-button v-if="state.gdDetail.derivative && !state.gdDetail.parentId" type="primary" class="btn-item" @click="handlerDerivativeWorkOrder(state.gdDetail, false)">
                    取消衍生
                  </a-button>
                  <a-button v-if="!state.gdDetail.derivative && !state.gdDetail.parentId" type="primary" class="btn-item" @click="handlerDerivativeWorkOrder(state.gdDetail, true)">
                    标记衍生
                  </a-button>
                </a-menu-item>
              </a-menu>
            </template>
          </a-dropdown>
        </div>
      </div>
      <!-- end vid_jvw772az8c 自定义模板_yiurj2x5rz -->
    </a-spin>
  </div>
</template>
<script setup lang="tsx">
  import {
      h, ref, reactive, toRaw, markRaw, watch, computed,
      onBeforeMount, onMounted, onBeforeUnmount, onUnmounted, onActivated, onDeactivated
    } from "vue";
    import { useRoute, useRouter } from 'vue-router';
    const router = useRouter();
    const route = useRoute();
    import { get, post, put, del, request, requestWithHeaders } from '@/utils/http/Axios';
    import { cloneDeep, localGet, merge, getDifferenceArray, traversalTreeStructure, checkCaseCondition, renderStringInTemplate, handleBreadcrumbJump, throttle, permission, getComponentParamsValue } from '@/utils/index';
    import { isNullOrEmpty, isEmptyArr, isNullOrUnDef, isContained, isArray, isEmpty, isObject } from '@/utils/is';
    import dayjs from 'dayjs';
    import { getPagePcChartsDataSourceConvert } from '@/utils/chart';
    import { message, notification, Modal } from 'ant-design-vue'
    import { propertyFormatByNumber, propertyFormatByPercentage, propertyFormatByDate, parseSubFromDataList } from '@/utils/format';
    import colorTheme from '@/design/custom-theme.json';
    
    import UserTableRecords from '@/model/UserTableRecords';
    import { getAppBaseUrl } from '@/utils/index';
    import { sendToken } from "@/hooks/useIframeToken";
    import { useSystemStore } from "@/store/modules/system";
    const systemStore = useSystemStore();
    



      // 获取传入的流程ID和组件参数
      const props = defineProps({
            'processInstanceId': {
            type: [String,Number,Boolean],
            default: undefined,
        },
      'type': {
            type: [String,Number],
            default: undefined,
        },
      'id': {
            type: [String,Number],
            default: undefined,
        },
      })
      const immediateWatch = (source, callback) => {
        watch(source, callback, {deep: true,immediate: true })
      }



  /* -------------------------- 属性定义 -------------------------- */

      const setTimeOutList = [];
      const pageLoading = reactive({
        loading: false,
        tip: undefined
      });
      const authInfo = localGet('app-user-store');




      // 处理校验
      const setSubFormName =(parentInfo, name)=>{
        return [parentInfo.parents, parentInfo.cycleIndex, name];
      }


  /* ========================== 属性定义 ========================== */


  /* -------------------------- 元素数据引用 -------------------------- */


  /* ========================== 元素数据引用 ========================== */


  /* -------------------------- 页面数据 -------------------------- */


  /* ========================== 页面数据 ========================== */



  /* -------------------------- 响应 -------------------------- */

  /* ========================== 响应 ========================== */


  /* -------------------------- 函数 -------------------------- */

  /* ========================== 函数 ========================== */


  /* -------------------------- 页面参数 -------------------------- */

    const pageParameter_state = reactive({
        'processInstanceId': props.processInstanceId ?? route.query.processInstanceId,
    })

  /* ========================== 页面参数 ========================== */


  /* -------------------------- 组件事件处理方法 -------------------------- */

    // ---------------------------- 组件数据同步 ----------------------------

    // ============================ 组件数据同步 ============================


  /* ========================== 组件事件处理方法 ========================== */


  /* -------------------------- 生命周期 -------------------------- */
  // 用于参数变更后重新执行自定义指令
      const queryUpdateFlag = ref(0);
      onMounted(() => { ;

    });

    onUnmounted(() => {
      // 销毁定时器
      setTimeOutList.forEach(({ repeat, timer }) => {
        repeat ?  clearInterval(timer): clearTimeout(timer);
      });
    });

  /* ========================== 生命周期 ========================== */


  /* -------------------------- 数据关联处理 -------------------------- */





  /* -------------------------- 表单数据同步 -------------------------- */
  /* ========================== 表单数据同步 ========================== */

  /* ========================== 数据关联处理 ========================== */


  /* -------------------------- 不同组件自定义的处理逻辑 -------------------------- */

  /* ========================== 不同组件自定义的处理逻辑 ========================== */


  // ================================定制化逻辑========================================
   //     富文本设置
      import { nextTick } from 'vue'
      import { QuillEditor, Quill } from '@vueup/vue-quill'
      import ImageUploader from 'quill-image-uploader'
      import '@vueup/vue-quill/dist/vue-quill.snow.css'
      const titleConfig = [
          { Choice: ' .ql-bold', title: '加粗' },
          { Choice: ' .ql-italic', title: '斜体' },
          { Choice: ' .ql-underline', title: '下划线' },
          { Choice: ' .ql-strike', title: '删除线' },
          { Choice: ' .ql-blockquote', title: '块引用' },
          { Choice: ' .ql-code-block', title: '插入代码' },
          { Choice: ' .ql-size', title: '字体大小' },
          { Choice: ' .ql-size', title: '字体大小' },
          { Choice: ' .ql-color', title: '字体颜色' },
          { Choice: ' .ql-background', title: '字体背景颜色' },
          { Choice: ' .ql-list[value="ordered"]', title: '有序列表' },
          { Choice: ' .ql-list[value="bullet"]', title: '无序列表' },
          { Choice: ' .ql-header[value="1"]', title: '1级标题' },
          { Choice: ' .ql-header[value="2"]', title: '2级标题' },
          { Choice: ' .ql-align', title: '对齐方式' },
          { Choice: ' .ql-clean', title: '清除字体格式' },
          { Choice: ' .ql-image', title: '图像' },
          { Choice: ' .ql-size .ql-picker-item[data-value="small"]', title: '小号' },
          { Choice: ' .ql-size .ql-picker-item[data-value="large"]', title: '大号' },
          { Choice: ' .ql-size .ql-picker-item[data-value="huge"]', title: '超大号' },
          { Choice: ' .ql-size .ql-picker-item:nth-child(2)', title: '标准' },
          { Choice: ' .ql-align .ql-picker-item:first-child', title: '居左对齐' },
          { Choice: ' .ql-align .ql-picker-item[data-value="center"]', title: '居中对齐' },
          { Choice: ' .ql-align .ql-picker-item[data-value="right"]', title: '居右对齐' },
          { Choice: ' .ql-align .ql-picker-item[data-value="justify"]', title: '两端对齐' }
      ]
      // 注册图片上传模块
      Quill.register('modules/imageUploader', ImageUploader)

      // 将本地文件转换为URL
      const getLocalImageURL = file => {
          return new Promise(resolve => {
              const reader = new FileReader()
              reader.onload = e => {
                  resolve(e.target.result)
              }
              reader.readAsDataURL(file)
          })
      }

      // 表单数据

      // Quill 编辑器选项
      const editorOption = ref({
          modules: {
              // imageUploader: {
              //     upload: async file => {
              //         const localUrl = await getLocalImageURL(file)
              //         return localUrl // 返回本地图片的 URL 进行预览
              //     }
              // },
              toolbar: [
                  ['bold', 'italic', 'underline', 'strike'], // 加粗，斜体，下划线，删除线
                  ['blockquote', 'code-block'], // 引用，代码块
                  [{ header: 1 }, { header: 2 }], // 标题1，标题2
                  [{ list: 'ordered' }, { list: 'bullet' }], // 有序列表，无序列表
                  [{ size: ['small', false, 'large', 'huge'] }], // 文字大小
                  [{ color: [] }, { background: [] }], // 字体颜色，背景颜色
                  [{ align: [] }], // 对齐
                  ['clean'], // 清除格式
                  ['image'] // 链接，图片，视频
              ]
              // ImageUploader: imageHandler
          }
      })

      // 将 dataURL 转换为 File 对象的辅助函数
      const dataURLtoFile = (dataurl, filename) => {
          const arr = dataurl.split(',')
          const mime = arr[0].match(/:(.*?);/)[1]
          const bstr = atob(arr[1])
          let n = bstr.length
          const u8arr = new Uint8Array(n)
          while (n--) {
              u8arr[n] = bstr.charCodeAt(n)
          }
          return new File([u8arr], filename, { type: mime })
      }
      // 上传API
      const uploadFileAPI = async file => {
          const data = new FormData()
          data.append('file', file)

          return post('/file-storage/api/v1/file/upload', data)
              .then(({ data: { fullUrl } }) => {
                  return { data: { fullUrl } }
              })
              .catch(error => {
                  console.error('上传图片出错:', error)
                  throw error // 抛出错误以供外部处理
              })
      }
      const { id } = props
      onMounted(() => {
          getAllUser()
          getPmName()
          getPmo()
          getAreaList()
          getCustomerList()
          getProjectList()
          getWorkType()
          getWarnList()
          getWtly()
          getClassfy()
      })
      const useId = ref()
      import { watchEffect } from 'vue'
      watchEffect(() => {
          if (props.id) {
              setTimeout(() => {
                  useId.value = props.id
                  getData()
              }, 500)
          }
      })
      const state = reactive({
          gdDetail: {},
          modalForm: {
              content: undefined,
              type: undefined,
              priority: undefined,
              questionSource: undefined,
              monitorScene: undefined,
              workHours: undefined,
              endTime: undefined,
              areaCode: undefined,
              projectId: undefined,
              milepostId: undefined,
              taskId: undefined,
              version: undefined,
              warningLevel: undefined,
              customer: undefined,
              production: undefined,
              environment: undefined,
              description: undefined,
              solverList: [],
              descriptionAttachmentList: [],
              qillData: ''
          },
          sonForm: {
              parentId: undefined,
              content: undefined,
              type: undefined,
              priority: undefined,
              questionSource: undefined,
              workHours: undefined,
              endTime: undefined,
              areaCode: undefined,
              projectId: undefined,

              version: undefined,
              customer: undefined,
              production: undefined,
              environment: undefined,
              description: undefined,
              solverList: [],
              descriptionAttachmentList: [],
              quillData: ''
          },
          modalTitle: '',
          addOrEditVisible: false,
          editSonVisible: false,
          allUser: [],
          warnList: [],
          wtlyList: [],
          pmoList: [],
          pmNameList: [],
          previewImage: '',
          previewVisible: false,
          // 工单类型
          workTypeList: [],
          monitorSceneList: [],
          environmentList: [],
          productList: [],
          customList: [],
          tagList: [],
          areaList: [],
          fatherLoading: false,
          deleteLoading: false,
          deleteVisible: false,
          sonLoading: false
      })
      function getData() {
          get(`/solution-ppm/api/v2/built-in-system-ppm/work_order/details/${useId.value}`).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              state.gdDetail = data.data.workOrderDto
          })
      }
      function sonDisabled(item) {
          return !(['未开始', '解决中'].includes(item.status) && item.tag !== 1 && item.myCreated)
      }
      function sopDisabled(item) {
          return item.tag !== 1 || ['无需解决', '已关闭', '已解决', '已回访'].includes(item.status)
      }
      function isCloseDisabled(item) {
          return (
              !(item.status === '已解决' && (item.myCreated || item.pmoOrNot)) &&
              !(item.status === '无需解决' && (item.myCreated || item.pmoOrNot))
          ) // 创建人或PMO关闭
      }
      function isResolvingDisabled(item) {
          return !(item.status === '未开始' && item.solvers)
      }
      function isNoNeedSolveDisabled(item) {
          return !((item.status === '未开始' && item.solvers) || (item.status === '解决中' && item.solvers))
          // !(item.status === '未开始' && item.solvers) || !(item.status === '解决中' && item.solvers)
      }
      function isResolvedDisabled(item) {
          return (
              // !(item.status === '未开始' && item.solvers) && // 解决人解决中
              !(item.status === '解决中' && item.solvers)
          )
      }
      function isReturnVisitDisabled(item) {
          return !(item.status === '已关闭' && (item.myCreated || item.pmoOrNot)) // 创建人或PMO回访
      }
      // 判断按钮是否可用的计算属性
      function isCirculationDisabled(item) {
          if (item.tag === 1) return true // 如果 tag 是 1，直接禁用按钮
          return !(
              (
                  (item.status === '未开始' && item.solvers) || // 未开始且有solvers
                  (item.status === '解决中' && item.solvers) || // 解决中且有solvers
                  (item.status === '待分发' && item.distributed) ||
                  item.tag === 1
              ) // 待分发且distributed为true
          )
      }
      function isEditDisabled(item) {
          return ['无需解决', '已关闭', '已解决'].includes(item.status)
      }
      //     新需求工单sop
      const newSopState = reactive({
          sopOkLoading: false,
          sopVisible: false,
          selectedRowKeys: [],
          sopTableData: [],
          //   sop父工单开始解决部分
          sopStartTableList: [],
          //   sop工单无需解决
          solvedSOPList: [],
          //   sop工单关闭
          sopCloseTableData: [],
          sopCloseVisible: false,
          //   sop已拒绝部分
          sopRemainingData: [],
          //   新建SOP子工单里的附件
          sopFileList: [],
          closeLoading: false,
          closeRemark: undefined
      })
      const sopColumns = [
          {
              title: 'SOP名称',
              dataIndex: 'sopName',
              align: 'center',
              ellipsis: true,
              customCell: ({ rowSpan }) => {
                  return {
                      rowSpan: rowSpan
                  }
              }
          },
          {
              title: 'SOP步骤',
              dataIndex: 'sopStep',
              align: 'center',
              ellipsis: true
          },
          {
              title: '解决角色',
              dataIndex: 'solverRole',
              align: 'center',
              ellipsis: true
          }
      ]
      function groupSopData(data) {
          let currentSopName = ''

          // 遍历数据，计算每一行的 rowSpan
          return data.map((item, index) => {
              if (currentSopName !== item.sopName) {
                  // 更新当前的标识符
                  currentSopName = item.sopName

                  // 计算这个组的 rowSpan
                  let rowSpan = 0
                  for (let i = index; i < data.length; i++) {
                      const currentItem = data[i]
                      if (currentSopName === currentItem.sopName) {
                          rowSpan += 1
                      } else {
                          break
                      }
                  }
                  item.rowSpan = rowSpan
              } else {
                  item.rowSpan = 0 // 如果是相同的组，重置 rowSpan
              }

              return item
          })
      }
      const currentAddSopRecord = ref({})
      function handleAddSopSon(record) {
          get(`/solution-ppm/api/v2/built-in-system-ppm/work_order/${record.id}/sop/steps`).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              // newSopState.sopTableData = groupSopData(data.data.filter(item => item.canCreated))
              newSopState.sopTableData = groupSopData(data.data)
              console.log(newSopState.sopTableData, 'asdas')
              currentAddSopRecord.value = record
              // TODO:获取sop列表
              newSopState.sopVisible = true
          })
      }
      // 新建sop子工单
      function cancelSop() {
          newSopState.sopVisible = false
          currentAddSopRecord.value = {}
          resetNewState()
      }
      const sopSonLoading = ref(false)
      function confirmSop() {
          const selectedSopList = newSopState.sopTableData.filter(item =>
              newSopState.selectedRowKeys.includes(item.sopStepId)
          )
          sopSonLoading.value = true
          const params = {
              attachmentList: newSopState.sopFileList,
              children: selectedSopList,
              parentId: currentAddSopRecord.value.id,
              endTime: currentAddSopRecord.value.endTime,
              monitorScene: currentAddSopRecord.value.monitorScene
          }
          post('/solution-ppm/api/v2/built-in-system-ppm/work_order/createSopChildren', params)
              .then(data => {
                  if (data.code !== 200) {
                      message.error(data.message)
                      return
                  }
                  message.success(data.message)
                  newSopState.sopVisible = false
                  resetNewState()
                  getData()
                  handleDone()
              })
              .finally(() => {
                  sopSonLoading.value = false
              })

          currentAddSopRecord.value = {}
      }
      function resetNewState() {
          newSopState.sopTableData = []
          newSopState.selectedRowKeys = []
          newSopState.sopFileList = []
      }
      const onSopSelectChange = selectedRowKeys => {
          console.log(selectedRowKeys, 'selectedRowKeys')
          newSopState.selectedRowKeys = selectedRowKeys
      }
      //     下载sop附件模板
      const downTemplateFileLoading = ref(false)
      function handleDownLoadSopTemplate(record) {
          downTemplateFileLoading.value = true
          post(`/solution-ppm/api/v2/built-in-system-ppm/work_order/download_template/${record.id}`, null, {
              responseType: 'blob'
          })
              .then(res => {
                  console.log(res)
                  if (res.type === 'application/octet-stream') {
                      downloadZip(res, '附件模板.zip')
                  } else {
                      message.info('没有模板可以下载')
                  }
                  // if (res.code) {
                  //     message.error(data.message)
                  //     return
                  // }
                  // downloadZip(res, '附件模板.zip')
              })
              .finally(() => {
                  downTemplateFileLoading.value = false
              })
      }
      function downloadZip(response, name) {
          const blob = new Blob([response], { type: 'application/zip;charset=utf-8' })
          const downloadElement = document.createElement('a')
          const href = window.URL.createObjectURL(blob)
          downloadElement.href = href
          downloadElement.download = name // 下载后文件名
          document.body.appendChild(downloadElement)
          downloadElement.click()
          document.body.removeChild(downloadElement)
          window.URL.revokeObjectURL(href)
          return href
      }
      // 父上传文件
      function handlerSopUpload(file) {
          const data = new FormData()
          data.append('file', file)

          post('/file-storage/api/v1/file/upload', data)
              .then(({ data: { fullUrl } }) => {
                  if (data) {
                      // 新文件对象
                      const newFile = {
                          uid: file.uid,
                          lastModified: file.lastModified,
                          name: file.name,
                          size: file.size,
                          type: file.type,
                          status: 'done',
                          url: fullUrl
                      }

                      // 去重，保留一个副本
                      newSopState.sopFileList = [
                          // 保留已存在文件（去除重复）
                          ...newSopState.sopFileList.filter(item => item.uid !== file.uid && item.name !== file.name),
                          // 添加新的文件
                          newFile
                      ]
                  }
                  state.fatherLoading = false
              })
              .catch(e => {
                  message.error('上传失败' + e)
              })

          return false
      }
      // 父移除文件
      function handlerSopRemove(file) {
          newSopState.sopFileList = newSopState.sopFileList.filter(item => item.uid !== file.uid)
      }
      //    新需求
      const newState = reactive({
          changeStatusLoading: false,
          isExpandAll: false,
          circulationVisible: false,
          resolvingVisible: false,
          resolvedVisible: false,
          circulationForm: {
              solverList: [],
              status: '流转'
          },
          resolvingForm: {
              solution: '',
              status: '解决中'
          },
          resolvedForm: {
              solution: '',
              attachmentList: [],
              status: '已解决',
              solutionDetail: ''
          },
          closeForm: {
              status: '关闭'
          },
          workOrderId: undefined
      })
      const circulationFormRef = ref(null)
      const resolvingFormRef = ref(null)
      const resolvedFormRef = ref(null)
      const newRules = {
          solutionDetail: [
              {
                  validator: (_, value) => {
                      // 如果是 HTML 字符串则先处理为文本
                      if (typeof value === 'string') {
                          const text = value.replace(/<[^>]+>/g, '').trim()
                          return text ? Promise.resolve() : Promise.reject(new Error('请输入解决方案详述'))
                      }

                      // 如果是 Delta（对象），提取纯文本
                      if (typeof value === 'object' && value?.ops) {
                          const plainText = value.ops
                              .map(op => {
                                  return typeof op.insert === 'string' ? op.insert : ''
                              })
                              .join('')
                              .trim()

                          return plainText ? Promise.resolve() : Promise.reject(new Error('请输入解决方案详述'))
                      }

                      return Promise.reject(new Error('请输入解决方案详述'))
                  },
                  trigger: 'blur'
              }
          ]
      }

      const resolvingQuillRef = ref(null)
      const resolvedQuillRef = ref(null)
      // 开始解决
      const currentResolvingData = ref({})
      function showResolving(record, parentId) {
          if (record.tag === 1) {
              get(`/solution-ppm/api/v2/built-in-system-ppm/work_order/${record.id}/sop/steps`).then(data => {
                  if (data.code !== 200) {
                      message.error(data.message)
                      return
                  }
                  newSopState.sopTableData = groupSopData(data.data)
                  // newSopState.sopTableData = groupSopData(data.data.filter(item => item.canCreated))
              })
          } else {
              newSopState.sopTableData = []
          }
          newSopState.selectedRowKeys = []
          currentResolvingData.value = record
          if (parentId) {
              currentResolvingData.value.addParentId = parentId
          } else {
              currentResolvingData.value.addParentId = record.id
          }
          newState.workOrderId = record.id
          newState.resolvingVisible = true
      }
      // 开始解决处理
      async function confirmResolving() {
          newState.changeStatusLoading = true
          try {
              const selectedSopList = newSopState.sopTableData.filter(item =>
                  newSopState.selectedRowKeys.includes(item.sopStepId)
              )
              newState.resolvingForm.workOrderId = currentResolvingData.value.id
              const params = {
                  attachmentList: newSopState.sopFileList,
                  children: selectedSopList,
                  parentId: currentResolvingData.value.addParentId,
                  endTime: currentResolvingData.value.endTime,
                  monitorScene: currentResolvingData.value.monitorScene
              }

              // 只有当 tag === 1 时，才先执行 createSopChildren
              if (currentResolvingData.value.tag === 1) {
                  const createRes = await post(
                      '/solution-ppm/api/v2/built-in-system-ppm/work_order/createSopChildren',
                      params
                  )
                  if (createRes.code !== 200) {
                      message.error(createRes.message)
                      return
                  }
              }

              // 调用 status_change 接口
              const statusChangeRes = await put(
                  '/solution-ppm/api/v2/built-in-system-ppm/work_order/status_change',
                  newState.resolvingForm
              )
              if (statusChangeRes.code !== 200) {
                  message.error(statusChangeRes.message)
                  return
              }

              message.success(statusChangeRes.message)
              cancelResolving()
              resetNewState()
              getData()
              handleDone()
          } catch (error) {
              message.error('操作失败，请重试')
              console.error('错误详情:', error)
          } finally {
              newState.changeStatusLoading = false
          }
      }

      function cancelResolving() {
          newState.resolvingVisible = false
      }
      // 已解决
      const resolvedData = ref({})
      function showResolved(record, parentId) {
          if (record.tag === 1) {
              get(`/solution-ppm/api/v2/built-in-system-ppm/work_order/${record.id}/sop/steps`).then(data => {
                  if (data.code !== 200) {
                      message.error(data.message)
                      return
                  }
                  // newSopState.sopTableData = groupSopData(data.data.filter(item => item.canCreated))
                  newSopState.sopTableData = groupSopData(data.data)
                  // newSopState.solvedSOPList = groupSopData(data.data.filter(item => item.solveByMe))
                  newSopState.solvedSOPList = groupSopData(data.data)
              })
          } else {
              newSopState.sopTableData = []
          }
          newSopState.selectedRowKeys = []
          resolvedData.value = record
          newState.resolvedVisible = true
          if (parentId) {
              resolvedData.value.addParentId = parentId
          } else {
              resolvedData.value.addParentId = record.id
          }
          newState.workOrderId = record.id
          get(`/solution-ppm/api/v2/built-in-system-ppm/work_order/details/${newState.workOrderId}`).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              rootState.responsibleParty = data.data.workOrderDto.responsibleParty
              rootState.businessType = data.data.workOrderDto.businessType
              rootState.rootCauseClassify = data.data.workOrderDto.rootCauseClassify
              newState.resolvedVisible = true
              nextTick(() => {
                  newState.resolvedForm.solution = data.data.workOrderDto.solution
                  newState.resolvedForm.attachmentList = data.data.workOrderDto.attachmentList

                  try {
                      const rootDetail = JSON.parse(data.data.workOrderDto.rootCauseAnalysis)
                      rootQuillEditor.value.setContents(rootDetail)
                  } catch (e) {
                      console.warn('rootQuillEditor 赋值失败（不阻断）:', e)
                  }

                  try {
                      const solutionDetail = JSON.parse(data.data.workOrderDto.solutionDetail)
                      resolvedQuillRef.value.setContents(solutionDetail)
                  } catch (e) {
                      console.warn('resolvedQuillRef 赋值失败（不阻断）:', e)
                  }
              })


          })
      }
      // 上传文件
      function handlerResolvedUpload(file) {
          newState.changeStatusLoading = true
          const data = new FormData()
          data.append('file', file)

          post('/file-storage/api/v1/file/upload', data)
              .then(({ data: { fullUrl } }) => {
                  if (data) {
                      // 新文件对象
                      const newFile = {
                          uid: file.uid,
                          lastModified: file.lastModified,
                          name: file.name,
                          size: file.size,
                          type: file.type,
                          status: 'done',
                          url: fullUrl
                      }

                      // 去重，保留一个副本
                      newState.resolvedForm.attachmentList = [
                          // 保留已存在文件（去除重复）
                          ...newState.resolvedForm.attachmentList.filter(
                              item => item.uid !== file.uid && item.name !== file.name
                          ),
                          // 添加新的文件
                          newFile
                      ]
                  }
                  newState.changeStatusLoading = false
              })
              .catch(e => {
                  message.error('上传失败' + e)
              })

          return false
      }
      // 移除文件
      function handlerResolvedRemove(file) {
          newState.resolvedForm.attachmentList = newState.resolvedForm.attachmentList.filter(
              item => item.uid !== file.uid
          )
      }
      // 已解决处理
      const deltaData = ref(null)
      const rootRef = ref(null)
      async function confirmResolved() {
          newState.changeStatusLoading = true
          try {
              await resolvedFormRef.value.validate().catch(errors => {
                  console.error('表单校验失败:', errors)
                  message.error('请检查表单填写是否正确')
                  throw new Error('表单校验未通过')
              })

              const deltaContent = resolvedQuillRef.value.getContents()
              deltaData.value = deltaContent // 保存一份 delta 数据

              const imageUploadPromises = []

              deltaContent.ops.forEach(op => {
                  if (op.insert && op.insert.image && op.insert.image.startsWith('data:')) {
                      const localSrc = op.insert.image
                      const file = dataURLtoFile(localSrc, 'image.png')

                      const uploadPromise = uploadFileAPI(file).then(({ data: { fullUrl } }) => {
                          op.insert.image = fullUrl
                      })

                      imageUploadPromises.push(uploadPromise)
                  }
              })

              await Promise.all(imageUploadPromises)

              // 如果 tag === 1，先调用 createSopChildren 接口
              if (resolvedData.value.tag === 1) {
                  const params = {
                      attachmentList: newSopState.sopFileList,
                      children: newSopState.sopTableData.filter(item =>
                          newSopState.selectedRowKeys.includes(item.sopStepId)
                      ),
                      parentId: resolvedData.value.addParentId,
                      endTime: resolvedData.value.endTime,
                      monitorScene: resolvedData.value.monitorScene
                  }

                  const createSopResponse = await post(
                      '/solution-ppm/api/v2/built-in-system-ppm/work_order/createSopChildren',
                      params
                  )

                  if (createSopResponse.code !== 200) {
                      message.error(createSopResponse.message)
                      return
                  }
              }

              // 构造最终状态变更数据，注意不要修改 form 本身
              const payload = {
                  ...newState.resolvedForm,
                  workOrderId: resolvedData.value.id,
                  status: '已解决',
                  solutionDetail: JSON.stringify(deltaData.value) // 仅提交结构化数据
              }

              const statusChangeResponse = await put(
                  '/solution-ppm/api/v2/built-in-system-ppm/work_order/status_change',
                  payload
              )

              if (statusChangeResponse.code !== 200) {
                  message.error(statusChangeResponse.message)
                  return
              }

              message.success(statusChangeResponse.message)
              cancelResolved()
              getData()
              handleDone()
          } catch (error) {
              // 可选：日志
          } finally {
              newState.changeStatusLoading = false
          }
      }
      function saveRoot() {
          rootRef.value.validate().then(async () => {
              newState.changeStatusLoading = true

              const params = {
                  responsibleParty: rootState.responsibleParty,
                  businessType: rootState.businessType,
                  rootCauseClassify: rootState.rootCauseClassify,
                  rootCauseAnalysis: '',
                  id: resolvedData.value.id
              }

              // === 单独处理 rootEditor 富文本图片上传 ===
              let rootDeltaContent = null
              try {
                  rootDeltaContent = rootQuillEditor.value.getContents()
                  const rootUploadTasks = rootDeltaContent.ops.map(async op => {
                      if (op.insert?.image?.startsWith('data:')) {
                          const file = dataURLtoFile(op.insert.image, 'image.png')
                          const {
                              data: { fullUrl }
                          } = await uploadFileAPI(file)
                          op.insert.image = fullUrl
                      }
                  })
                  await Promise.all(rootUploadTasks)
                  params.rootCauseAnalysis = JSON.stringify(rootDeltaContent)
              } catch (e) {
                  console.error('处理 rootQuillEditor 出错：', e)
                  // 同样不 return，继续提交
              }

              // === 提交接口 ===
              put('/solution-ppm/api/v2/built-in-system-ppm/work_order/root_cause_modify', params)
                  .then(data => {
                      if (data.code !== 200) {
                          message.error(data.message)
                          return
                      }
                      confirmResolved()
                  })
                  .finally(() => {
                      newState.changeStatusLoading = false
                  })
          })
      }
      function cancelResolved() {
          newState.resolvedVisible = false
      }
      // 重新打开
      function handlerReOpen(item) {
          const params = {
              workOrderId: item.id,
              status: '未开始'
          }
          if (item.actualStartTime) {
              params.status = '解决中'
          } else {
              params.status = '未开始'
          }
          put('/solution-ppm/api/v2/built-in-system-ppm/work_order/status_change', params).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              message.success(data.message)
              getData()
              handleDone()
          })
      }
      // 无需解决
      const deleteRef = ref(null)
      const closeRef = ref(null)
      const noNeedRef = ref(null)
      const sonState = reactive({
          modalTitle: '',
          noNeedVisible: false,
          noNeedLoading: false,
          noNeedRemark: undefined,
          deleteVisible: false,
          deleteRemark: undefined,
          deleteLoading: false
      })
      const noNeedData = ref({})
      function showNoNeed(item, parentId) {
          console.log(item)
          newSopState.selectedRowKeys = []
          noNeedData.value = item
          if (parentId) {
              noNeedData.value.addParentId = parentId
          } else {
              noNeedData.value.addParentId = item.id
          }
          if (item.tag === 1) {
              get(`/solution-ppm/api/v2/built-in-system-ppm/work_order/${item.id}/sop/steps`).then(data => {
                  if (data.code !== 200) {
                      message.error(data.message)
                      return
                  }
                  // newSopState.sopTableData = groupSopData(data.data.filter(item => item.canCreated))
                  newSopState.sopTableData = groupSopData(data.data)
              })
          } else {
              newSopState.sopTableData = []
          }
          sonState.noNeedRemark = item.remark
          sonState.noNeedVisible = true
      }
      // 无需解决处理
      async function submitNoNeed() {
          sonState.noNeedLoading = true
          try {
              await noNeedRef.value.validate()
              const selectedSopList = newSopState.sopTableData.filter(item =>
                  newSopState.selectedRowKeys.includes(item.sopStepId)
              )
              const params = {
                  attachmentList: newSopState.sopFileList,
                  children: selectedSopList,
                  parentId: noNeedData.value.addParentId,
                  endTime: noNeedData.value.endTime,
                  monitorScene: noNeedData.value.monitorScene
              }

              // 只有当 tag === 1 时，才先执行 createSopChildren
              if (noNeedData.value.tag === 1) {
                  const createRes = await post(
                      '/solution-ppm/api/v2/built-in-system-ppm/work_order/createSopChildren',
                      params
                  )
                  if (createRes.code !== 200) {
                      message.error(createRes.message)
                      return
                  }
              }

              // 调用 status_change 接口
              const statusChangeRes = await put('/solution-ppm/api/v2/built-in-system-ppm/work_order/status_change', {
                  remark: sonState.noNeedRemark,
                  status: '无需解决',
                  workOrderId: noNeedData.value.id
              })
              if (statusChangeRes.code !== 200) {
                  message.error(statusChangeRes.message)
                  return
              }

              message.success(statusChangeRes.message)
              cancelNoNeed()
              resetNewState()
              getData()
              handleDone()
          } catch (error) {
              if (error?.errorFields) {
                  // ✅ 这里确保只有校验失败时才会显示
                  message.error('请检查表单填写是否正确')
              } else {
                  message.error('操作失败，请重试')
                  console.error('错误详情:', error)
              }
          } finally {
              sonState.noNeedLoading = false
          }
      }
      function cancelNoNeed() {
          sonState.noNeedVisible = false
          sonState.noNeedRemark = undefined
          noNeedData.value = {}
      }
      // 工单开始关闭
      const currentCloseData = ref({})
      function handlerClose(item, parentId) {
          console.log(item)
          newSopState.selectedRowKeys = []
          currentCloseData.value = item
          if (parentId) {
              currentCloseData.value.addParentId = parentId
          } else {
              currentCloseData.value.addParentId = item.id
          }
          if (item.tag === 1) {
              get(`/solution-ppm/api/v2/built-in-system-ppm/work_order/${item.id}/sop/steps`).then(data => {
                  if (data.code !== 200) {
                      message.error(data.message)
                      return
                  }
                  // newSopState.sopTableData = groupSopData(data.data.filter(item => item.canCreated))
                  newSopState.sopTableData = groupSopData(data.data)
              })
          } else {
              newSopState.sopTableData = []
          }

          newSopState.sopCloseVisible = true
      }
      // 工单关闭处理
      // 工单确定关闭
      async function confirmSopClose() {
          newSopState.closeLoading = true
          try {
              // ✅ 直接 await 表单校验，不需要 catch
              await closeRef.value.validate()

              const selectedSopList = newSopState.sopTableData.filter(item =>
                  newSopState.selectedRowKeys.includes(item.sopStepId)
              )
              const params = {
                  attachmentList: newSopState.sopFileList,
                  children: selectedSopList,
                  parentId: currentCloseData.value.addParentId,
                  endTime: currentCloseData.value.endTime,
                  monitorScene: currentCloseData.value.monitorScene
              }

              // 只有当 tag === 1 时，才先执行 createSopChildren
              if (currentCloseData.value.tag === 1) {
                  const createRes = await post(
                      '/solution-ppm/api/v2/built-in-system-ppm/work_order/createSopChildren',
                      params
                  )
                  if (createRes.code !== 200) {
                      message.error(createRes.message)
                      return
                  }
              }

              // 调用 status_change 接口
              const statusChangeRes = await put('/solution-ppm/api/v2/built-in-system-ppm/work_order/status_change', {
                  remark: newSopState.closeRemark,
                  status: '已关闭',
                  workOrderId: currentCloseData.value.id
              })
              if (statusChangeRes.code !== 200) {
                  message.error(statusChangeRes.message)
                  return
              }

              message.success(statusChangeRes.message)
              cancelClose()
              resetNewState()
              getData()
              handleDone()
          } catch (error) {
              if (error?.errorFields) {
                  // ✅ 这里确保只有校验失败时才会显示
                  message.error('请检查表单填写是否正确')
              } else {
                  message.error('操作失败，请重试')
                  console.error('错误详情:', error)
              }
          } finally {
              newSopState.closeLoading = false
          }
      }
      function cancelClose() {
          newSopState.sopCloseVisible = false
          newSopState.closeRemark = undefined
          currentCloseData.value = {}
      }
      // 已回访
      function handleReturnVisit(item) {
          const params = {
              workOrderId: item.id,
              status: '已回访'
          }
          newState.changeStatusLoading = true
          put('/solution-ppm/api/v2/built-in-system-ppm/work_order/status_change', params).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  newState.changeStatusLoading = false
                  return
              }
              message.success(data.message)
              getData()
              handleDone()
          })
      }
      // 标记衍生
      function handlerDerivativeWorkOrder(item, flag) {
          put(`/solution-ppm/api/v2/built-in-system-ppm/work_order/switchDerivative/${item.id}`).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              message.success(data.message)
              getData()
              handleDone()
          })
      }
      // 编辑工单
      const currentData = ref({})
      //     编辑工单
      async function handleEdit(record) {
          await resetCurrentData()
          currentData.value = record
          await Object.assign(state.modalForm, record)
          await getMonitorSceneList()
          // 按顺序调用函数
          await getCustomerList() // 获取客户列表
          await getProjectList() // 获取项目列表
          await getEnvironmentList() // 获取环境列表
          await getProductList() // 获取产品列表

          // 显示模态框
          state.addOrEditVisible = true

          // 使用 nextTick 确保 DOM 更新后再执行
          nextTick(() => {
              get(`/solution-ppm/api/v2/built-in-system-ppm/work_order/details/${record.id}`).then(data => {
                  let descriptionData = JSON.parse(data.data.workOrderDto.description)
                  quillEditor.value.setContents(descriptionData)
              })
          })

          state.modalTitle = '编辑工单'
      }
      function resetCurrentData() {
          currentData.value = {}
      }
      // 客户
      function getCustomerList() {
          get(
              `/solution-ppm/api/v2/built-in-system-ppm/work_order/customer?areaCode=${
                  state.modalForm.areaCode ? state.modalForm.areaCode : ''
              }`
          ).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              state.customList = data.data
          })
      }
      // 项目
      function getProjectList() {
          if (state.modalForm.areaCode) {
              get(
                  `/solution-ppm/api/v2//built-in-system-ppm/work_order/project_by_area_code/${state.modalForm.areaCode}`
              ).then(data => {
                  if (data.code !== 200) {
                      message.error(data.message)
                      return
                  }
                  state.projectList = data.data
              })
          } else {
              get(`/solution-ppm/api/v2//built-in-system-ppm/work_order/project_by_area_code/0`).then(data => {
                  if (data.code !== 200) {
                      message.error(data.message)
                      return
                  }
                  state.projectList = data.data
              })
          }
      }
      // 项目阶段
      function getMilepostList() {
          get(
              `/solution-ppm/api/v2/built-in-system-ppm/work_order/milepost_by_project_id/${state.modalForm.projectId}`
          ).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              state.milepostList = data.data
          })
      }

      // 任务
      function getTaskList() {
          get(
              `/solution-ppm/api/v2/built-in-system-ppm/delivery_task/get_by_milepost_id/${state.modalForm.milepostId}`
          ).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              state.taskList = data.data
          })
      }
      // 获取环境
      function getEnvironmentList() {
          let customerId = state.customList.find(item => item.name === state.modalForm.customer)?.id
          console.log(customerId)
          get(`/solution-ppm/api/v2/built-in-system-ppm/work_order/env?customerId=${customerId ? customerId : ''}`).then(
              data => {
                  state.environmentList = data.data
              }
          )
      }
      // 产品
      function getProductList() {
          let envId = state.environmentList.find(item => item.name === state.modalForm.environment)?.id
          get(`/solution-ppm/api/v2/built-in-system-ppm/work_order/product?envId=${envId ? envId : ''}`).then(data => {
              state.productList = data.data
          })
      }
      // 工单类型
      // 获取告警级别list
      function getWarnList() {
          get('/solution-ppm/api/v2/built-in-system-ppm/dictionary/search/GD.GJJB').then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              state.warnList = data.data.map(item => {
                  return {
                      label: item.itemName,
                      value: item.itemCode
                  }
              })
          })
      }
      // 问题来源
      // 获取问题来源
      function getWtly() {
          get('/solution-ppm/api/v2/built-in-system-ppm/dictionary/search/GD.WTLY').then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              state.wtlyList = data.data.map(item => {
                  return {
                      label: item.itemName,
                      value: item.itemName
                  }
              })
          })
      }
      // 获取工单类型字典值
      function getWorkType() {
          get('/solution-ppm/api/v2/built-in-system-ppm/dictionary/search/GD.GDLX').then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              state.workTypeList = data.data.map(item => {
                  return {
                      label: item.itemName,
                      value: item.itemName
                  }
              })
          })
      }
      // 获取监控场景list
      function getMonitorSceneList(flag) {
          const params = flag ? state.filter.type : state.modalForm.type
          get(`/solution-ppm/api/v2/built-in-system-ppm/dictionary/search/${params}`).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              state.monitorSceneList = data.data.map(item => {
                  return {
                      label: item.itemName,
                      value: item.itemCode
                  }
              })
          })
      }
      // 监控场景
      function getPmo() {
          get('/solution-ppm/api/v2/built-in-system-ppm/work_order/role/search/PMO').then(data => {
              state.pmoList = data.data.map(item => {
                  return {
                      label: item,
                      value: item
                  }
              })
          })
      }
      function getPmName() {
          get('/solution-ppm/api/v2/built-in-system-ppm/work_order/role/search/PM').then(data => {
              state.pmNameList = data.data.map(item => {
                  return {
                      label: item,
                      value: item
                  }
              })
          })
      }
      function getAllUser() {
          get('/solution-ppm/api/v2/built-in-system-ppm/pmgf/get/allUser').then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              state.allUser = data.data.userDtoList
          })
      }
      // 区域
      function getAreaList() {
          get('/solution-ppm/api/v2/built-in-system-ppm/work_order/area_info').then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              state.areaList = data.data.map(item => {
                  return {
                      label: item.areaName,
                      value: item.areaCode
                  }
              })
          })
      }
      function getClassfy() {
          get('/solution-ppm/api/v2/built-in-system-ppm/dictionary/search/GD.GYGL').then(data => {
              state.tagList = data.data.map(item => ({
                  label: item.itemName,
                  value: item.itemName
              }))
          })
      }
      //     父工单提交表单
      const quillEditor = ref(null) // 引用QuillEditor组件
      const formRef = ref(null) // 引用QuillEditor组件
      function submit() {
          formRef.value.validate().then(async () => {
              state.fatherLoading = true
              const deltaContent = quillEditor.value.getContents()

              const imageUploadPromises = []

              deltaContent.ops.forEach(op => {
                  if (op.insert && op.insert.image && op.insert.image.startsWith('data:')) {
                      const localSrc = op.insert.image

                      // 如果是 base64 图片，上传并替换为 URL
                      const file = dataURLtoFile(localSrc, 'image.png') // 将 base64 转换为 File 对象

                      const uploadPromise = uploadFileAPI(file).then(({ data: { fullUrl } }) => {
                          // 替换 op 中的 base64 URL 为服务器返回的 URL
                          op.insert.image = fullUrl
                      })

                      imageUploadPromises.push(uploadPromise)
                  }
              })
              try {
                  await Promise.all(imageUploadPromises)
                  if (currentData.value.id) {
                      // 编辑保存逻辑
                      const params = { ...state.modalForm }
                      params.description = JSON.stringify(deltaContent)
                      put('/solution-ppm/api/v2/built-in-system-ppm/work_order', params)
                          .then(data => {
                              if (data.code !== 200) {
                                  message.error(data.message)
                                  return
                              }
                              message.success(data.message)
                              state.addOrEditVisible = false
                              resetFather()
                              getData()
                              handleDone()
                          })
                          .finally(() => {
                              state.fatherLoading = false
                          })
                  } else {
                      // 新建保存逻辑
                      const params = { ...state.modalForm }
                      params.description = JSON.stringify(deltaContent)
                      post('/solution-ppm/api/v2/built-in-system-ppm/work_order', params)
                          .then(data => {
                              if (data.code !== 200) {
                                  message.error(data.message)
                                  return
                              }
                              message.success(data.message)
                              state.addOrEditVisible = false
                              resetFather()
                              getData()
                              handleDone()
                          })
                          .finally(() => {
                              state.fatherLoading = false
                          })
                  }
              } catch (error) {
                  state.fatherLoading = false
                  console.error('图片上传失败', error)
                  return // 终止提交
              }
          })
      }
      function resetFather() {
          state.modalForm = {
              content: undefined,
              type: undefined,
              priority: undefined,
              questionSource: undefined,
              workHours: undefined,
              endTime: undefined,
              areaCode: undefined,
              projectId: undefined,
              milepostId: undefined,
              taskId: undefined,
              version: undefined,
              warningLevel: undefined,
              customer: undefined,
              production: undefined,
              environment: undefined,
              description: undefined,
              monitorScene: undefined,
              solverList: [],
              qillData: ''
          }
      }
      // 流转
      function showCirculation(record) {
          newState.circulationVisible = true
          newState.workOrderId = record.id
      }
      // 多选框改成单选
      function changeStatusSolverChange(value) {
          // if (Array.isArray(value) && value.length > 1) {
          //     newState.circulationForm.solverList = [value[0]] // 只保留第一个选项
          // }
          if (Array.isArray(value)) {
              newState.circulationForm.solverList = [value[value.length - 1]] // 只保留最后一个选项
          } else {
              newState.circulationForm.solverList = [value] // 如果不是数组，说明只选中一个选项
          }
      }
      // 流转处理
      function confirmCirculation() {
          circulationFormRef.value.validate().then(() => {
              newState.changeStatusLoading = true
              newState.circulationForm.workOrderId = newState.workOrderId
              newState.circulationForm.status = '未开始'
              put('/solution-ppm/api/v2/built-in-system-ppm/work_order/status_change', newState.circulationForm)
                  .then(data => {
                      if (data.code !== 200) {
                          message.error(data.message)
                          return
                      }
                      message.success(data.message)
                      cancelCirculation()
                      getData()
                      handleDone()
                  })
                  .finally(() => {
                      newState.changeStatusLoading = false
                      cancelCirculation()
                  })
          })
      }
      function cancelCirculation() {
          newState.circulationVisible = false
          newState.circulationForm = {
              solverList: [],
              status: '流转'
          }
      }
      // 删除
      function toDelete(record) {
          resetCurrentData()
          currentData.value = record
          state.deleteVisible = true
      }
      // 删除处理
      function handleDelete() {
          deleteRef.value.validate().then(() => {
              state.deleteLoading = true
              del(`/solution-ppm/api/v2/built-in-system-ppm/work_order/${currentData.value.id}`)
                  .then(data => {
                      if (data.code !== 200) {
                          message.error(data.message)
                          return
                      }
                      message.success(data.message)
                      state.deleteVisible = false
                      getData()
                      handleDone()
                  })
                  .finally(() => {
                      state.deleteLoading = false
                  })
          })
      }
      // 催办处理
      // 提醒
      function toRmind(id) {
          get(`/solution-ppm/api/v2/built-in-system-ppm/work_order/remind/${id}`).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              message.success('已经向工单关联人员发送提醒解决通知')
          })
      }
      //     子工单编辑
      function editSon(record) {
          resetCurrentData()
          currentData.value = record
          sonState.modalTitle = '编辑子工单'
          state.editSonVisible = true
          Object.assign(state.sonForm, record)
          nextTick(() => {
              get(`/solution-ppm/api/v2/built-in-system-ppm/work_order/details/${record.id}`).then(data => {
                  let descriptionData = JSON.parse(data.data.workOrderDto.description)
                  sonQuillRef.value.setContents(descriptionData)
              })
          })
      }
      const sonRef = ref(null)
      const sonQuillRef = ref(null)

      function cancelSon() {
          resetSon()
          state.editSonVisible = false
      }
      function resetSon() {
          state.sonForm = {
              parentId: undefined,
              content: undefined,
              type: undefined,
              priority: undefined,
              questionSource: undefined,
              workHours: undefined,
              endTime: undefined,
              areaCode: undefined,
              projectId: undefined,
              version: undefined,
              customer: undefined,
              production: undefined,
              environment: undefined,
              description: undefined,
              solverList: [],
              quillData: ''
          }
          currentData.value = {}
      }
      async function submitSon() {
          state.sonLoading = true
          sonRef.value.validate().then(async () => {
              const deltaContent = sonQuillRef.value.getContents()
              const imageUploadPromises = []

              deltaContent.ops.forEach(op => {
                  if (op.insert && op.insert.image && op.insert.image.startsWith('data:')) {
                      const localSrc = op.insert.image

                      // 如果是 base64 图片，上传并替换为 URL
                      const file = dataURLtoFile(localSrc, 'image.png') // 将 base64 转换为 File 对象

                      const uploadPromise = uploadFileAPI(file).then(({ data: { fullUrl } }) => {
                          // 替换 op 中的 base64 URL 为服务器返回的 URL
                          op.insert.image = fullUrl
                      })

                      imageUploadPromises.push(uploadPromise)
                  }
              })

              try {
                  await Promise.all(imageUploadPromises)

                  if (currentData.value.id) {
                      // 编辑保存逻辑
                      const params = { ...state.sonForm }
                      params.description = JSON.stringify(deltaContent)
                      put('/solution-ppm/api/v2/built-in-system-ppm/work_order', params)
                          .then(data => {
                              if (data.code !== 200) {
                                  message.error(data.message)
                                  return
                              }
                              message.success(data.message)
                              state.editSonVisible = false
                              resetSon()
                              getData()
                              handleDone()
                          })
                          .finally(() => {
                              state.sonLoading = false
                          })
                  } else {
                      // 新建保存逻辑
                      const params = { ...state.sonForm }
                      params.description = JSON.stringify(deltaContent)
                      post('/solution-ppm/api/v2/built-in-system-ppm/work_order', params)
                          .then(data => {
                              if (data.code !== 200) {
                                  message.error(data.message)
                                  return
                              }
                              message.success(data.message)
                              state.editSonVisible = false
                              resetSon()
                              getData()
                              handleDone()
                          })
                          .finally(() => {
                              state.sonLoading = false
                          })
                  }
              } catch (error) {
                  state.sonLoading = false
                  console.error('图片上传失败', error)
                  return // 终止提交
              }
          })
      }
      // 新建子工单
      function handleAddSon(record) {
          resetCurrentData()
          // if (record.status !== '解决中' || record.status === '已关闭' || record.status === '已回访') {
          //     message.info('请将父工单状态变更为解决中后重试')
          //     return
          // }
          console.log(record)
          sonState.modalTitle = '新建子工单'
          state.sonForm.solverList = record.solverList
          state.editSonVisible = true
          state.sonForm.parentId = record.id
          sonQuillRef.value.setContents('')

          // nextTick(() => {
          //   initSonTitle()
          // })
      }
      //     新需求工单sop
      //     根因分析
      const rootState = reactive({
          // 责任方
          responsibleParty: undefined,
          responsiblePartyList: [],
          // 业务类型
          businessType: undefined,
          businessTypeList: [],
          rootCauseClassifyList: undefined,
          rootCauseClassify: [],
          // 根因分析
          belongList: [],
          tagList: [],
          rootCauseFlag: false,
          tipVisible: false
      })
      const rootQuillEditor = ref(null)
      // 获取责任方
      function getResponsiblePartyList() {
          get('/solution-ppm/api/v2/built-in-system-ppm/dictionary/search/GD.ZRF').then(data => {
              rootState.responsiblePartyList = data.data
          })
      }

      // 根据责任方获取业务类型
      function getBusinessTypeList() {
          let envId = rootState.responsiblePartyList.find(item => item.itemName === rootState.responsibleParty)?.itemCode
          console.log(envId)
          get(`/solution-ppm/api/v2/built-in-system-ppm/dictionary/search/${envId}`).then(data => {
              rootState.businessTypeList = data.data
          })
      }

      // 根据业务类型获取根因分析
      function getRootCauseClassifyList() {
          let envId = rootState.businessTypeList.find(item => item.itemName === rootState.businessType)?.itemCode
          get(`/solution-ppm/api/v2/built-in-system-ppm/dictionary/search/${envId}`).then(data => {
              rootState.rootCauseClassifyList = data.data.map(item => {
                  return {
                      ...item
                  }
              })
          })
      }
      // 保存切换前值
      const preState = reactive({
          responsibleParty: undefined,
          businessType: undefined,
          rootCauseClassify: undefined
      })

      // 弹窗控制
      const tipState = reactive({
          visible: false,
          pendingField: '', // 'responsibleParty' | 'businessType' | 'rootCauseClassify'
          nextValue: undefined
      })

      // 判断富文本是否有内容
      function hasEditorContent() {
          const content = rootQuillEditor.value?.getText() || ''
          return content.trim().length > 0
      }

      // === 责任方 change ===
      function responsiblePartyChange(nextVal) {
          if (hasEditorContent()) {
              tipState.visible = true
              tipState.pendingField = 'responsibleParty'
              tipState.nextValue = nextVal
              // 还原选择框临时值
              rootState.responsibleParty = preState.responsibleParty
              return
          }
          applyResponsiblePartyChange(nextVal)
      }
      function applyResponsiblePartyChange(val) {
          rootState.responsibleParty = val
          preState.responsibleParty = val
          rootState.businessType = undefined
          preState.businessType = undefined
          rootState.rootCauseClassify = undefined
          preState.rootCauseClassify = undefined
          clearEditor()
          getBusinessTypeList()
      }

      // === 业务类型 change ===
      function businessTypeChange(nextVal) {
          if (hasEditorContent()) {
              tipState.visible = true
              tipState.pendingField = 'businessType'
              tipState.nextValue = nextVal
              rootState.businessType = preState.businessType
              return
          }
          applyBusinessTypeChange(nextVal)
      }
      function applyBusinessTypeChange(val) {
          rootState.businessType = val
          preState.businessType = val
          rootState.rootCauseClassify = undefined
          preState.rootCauseClassify = undefined
          clearEditor()
          getRootCauseClassifyList()
      }

      // === 根因分析 change ===
      function rootCauseClassifyChange(nextVal) {
          if (hasEditorContent()) {
              tipState.visible = true
              tipState.pendingField = 'rootCauseClassify'
              tipState.nextValue = nextVal
              rootState.rootCauseClassify = preState.rootCauseClassify
              return
          }
          applyRootCauseClassifyChange(nextVal)
      }
      function applyRootCauseClassifyChange(val) {
          rootState.rootCauseClassify = val
          preState.rootCauseClassify = val
          const selected = rootState.rootCauseClassifyList.find(item => item.itemName === val)
          const description = selected?.description || ''
          setEditorText(description)
      }

      // === 弹窗确认 ===
      function confirmRoot() {
          const field = tipState.pendingField
          const val = tipState.nextValue

          if (field === 'responsibleParty') {
              applyResponsiblePartyChange(val)
          } else if (field === 'businessType') {
              applyBusinessTypeChange(val)
          } else if (field === 'rootCauseClassify') {
              applyRootCauseClassifyChange(val)
          }

          tipState.visible = false
      }

      // 弹窗取消
      function cancelRoot() {
          tipState.visible = false
      }

      // 清空富文本
      function clearEditor() {
          rootQuillEditor.value?.setText('')
      }

      // 赋值富文本
      function setEditorText(text) {
          nextTick(() => {
              rootQuillEditor.value?.setText(text)
          })
      }
      import { watchEffect } from 'vue'
      // 初始赋值 preState
      watchEffect(() => {
          preState.responsibleParty = rootState.responsibleParty
          preState.businessType = rootState.businessType
          preState.rootCauseClassify = rootState.rootCauseClassify
      })
      const emit = defineEmits(['refresh'])

      function handleDone() {
          // 子组件某操作完成
          emit('refresh')
      }
</script>
<style lang="less" scoped>
  .page_root {
  width: 100%;
  height: 100%;
  overflow: auto;
  }
  .page_root :deep(.@{ant-prefix}-spin-nested-loading),
  .page_root :deep(.@{ant-prefix}-spin-container)
   {
      height: 100%;
  }
  .page_root :deep(.@{ant-prefix}-spin-container .@{ant-prefix}-table-wrapper)
   {
      display: flex;
      flex-flow: column nowrap;
      justify-content: flex-start;
  }
  .page_root :deep(.@{ant-prefix}-table)
   {
    flex: auto;
    overflow: auto;
  }
  .table-moreBtn_down {
    overflow: hidden; white-space: nowrap; text-overflow: ellipsis; width: 100px;
  }

  .table-moreBtn_menu :deep(.table-moreBtn_menu-item):hover {
    background: #ebf1ff;
  }

  /*  表格树结构样式处理，展开按钮层级增加*/
  :deep(.@{ant-prefix}-table-row-expand-icon) {
    z-index: 1;
  }
  /*  表格树结构 由于每个表格项采用自定义组件，使用绝对定位布局，开启树结构导致显示异常，暂时使用层级定位位置 */
  :deep(.@{ant-prefix}-table-row-level-1 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 15px !important;
    width: calc(100% - 15px);
  }
  :deep(.@{ant-prefix}-table-row-level-2 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 30px !important;
    width: calc(100% - 30px);
  }
  :deep(.@{ant-prefix}-table-row-level-3 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 45px !important;
    width: calc(100% - 45px);
  }
  :deep(.@{ant-prefix}-table-row-level-4 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 60px !important;
    width: calc(100% - 60px);
  }

  /* 穿梭框改变默认样式，为根据组件样式控制左右栏宽度。 */
  :deep(.@{ant-prefix}-transfer-list)
   {
      height: 100%;
      width: 50%;
  }


  /*样式*/
      .body {
          background-color: #fff;
          height: 100%;
      }
      .father-last {
          display: flex;
          gap: 16px;
      }
      /*工单SOP*/
      .modal-table :deep(.@{ant-prefix}-table-thead) > tr > th {
          background: #3875ff;
          font-size: 14px;
          font-family: arial, helvetica, 'microsoft yahei';
          font-weight: 600;
          color: #ffffff;
          border-bottom: 1px solid #3875ff;
          padding: 8px 16px;
      }
      .modal-table :deep(.table-striped-odd) td {
          background-color: #ffffff;
      }
      .modal-table :deep(.table-striped-even) td {
          background-color: #f8fafc;
      }
      .modal-table :deep(.@{ant-prefix}-table-tbody) tr > td {
          font-size: 14px;
          font-family: arial, helvetica, 'microsoft yahei';
          font-weight: 400;
          color: #262626;
          padding: 8px 16px;
          word-break: break-all;
          R .cell-wrapper {
              padding: 0 16px;
          }
      }
      .sop-start-tip {
          height: 40px;
          padding: 12px 16px;
          background: rgba(250, 173, 20, 0.1);
          display: flex;
          font-size: 14px;
          color: #262626;
          font-weight: 400;
          align-items: center;
          gap: 8px;
          margin-bottom: 16px;
      }
      .resolved-div {
          display: flex;
          padding: 10px 16px;
          background: rgba(250, 173, 20, 0.1);
          font-size: 14px;
          color: #262626;
          font-weight: 400;
          gap: 8px;
          margin-bottom: 16px;
      }
      .change-status :deep(.ql-snow .ql-editor) img {
          width: 200px;
      }
      .change-status-tip {
          height: 52px;
          line-height: 52px;
          font-size: 14px;
          color: #262626;
          font-weight: 400;
      }
      .change-status-resolved {
          display: flex;
          gap: 16px;
      }
      :deep(.ql-blank) {
          min-height: 110px;
          background: #ffffff;
      }
      :deep(.ql-editor) {
          min-height: 110px;
          background: #ffffff;
      }
      .no-need-tip {
          display: flex;
          padding: 10px 16px;
          background: rgba(250, 173, 20, 0.1);
          font-size: 14px;
          color: #262626;
          font-weight: 400;
          gap: 8px;
          margin-bottom: 16px;
          align-items: center;
      }
      .form-content :deep(.ant3-form-item-label) {
          width: 145px;
      }
      .form-content :deep(.ant3-input-number),
      :deep(.ant3-picker) {
          width: 100%;
      }
      .description-tip {
          font-size: 14px;
          color: #262626;
          letter-spacing: 0;
          text-align: center;
          font-weight: 400;
          background: rgba(250, 100, 0, 0.1);
          border: 1px solid #fa6400;
          border-radius: 2px;
          padding: 6px 16px;
          margin-bottom: 16px;
      }
      .tip-img {
          width: 16px;
          height: 16px;
          color: #fa6400;
      }
      .sop-son-icon {
          display: inline-block;
          width: 16px;
          height: 16px;
          background-color: red;
      }
      .btn-body {
          display: flex;
          align-items: center;
      }
      .ant3-btn:hover {
          background-color: #3875ff;
          color: #fff;
      }
      .change-status :deep(.ant3-form-item-label) {
          width: 110px;
      }
      /*样式*/
</style>